#include "tester.h"

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <mpi.h>

#include "portable_time.h"
#include "solver_stable.h"

double f/*_prev*/(double x, double y)
{
    return 2 * (x + y) - 2 * (x * x + y * y);
}

/*double f(double x, double y)
{
    int n = 400;
    double hx = x / n;
    double hy = y / n;
    double cx, cy;
    
    double sum = 0.0;
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            cx = i * hx + 0.5 * hx;
            cy = j * hy + 0.5 * hy;
            sum += sin(exp(2 * (x + y) - 2 * (x * x + y * y)) - 1) * 
                cos(exp(2 * (x + y) - 2 * (x * x + y * y)) - 1) / 
                exp(2 * (x + y) - 2 * (x * x + y * y));
        }
    }

    return sum;
}*/

bool test(SolverFunc solve)
{
	int pid;
	MPI_Comm_rank(MPI_COMM_WORLD, &pid);

	bool result = true;

	Area area;
	area.a = 0.0;
	area.b = 1.0;
	area.n = 100;
	int n = area.n;
	double h = (area.b - area.a) / n;
	double eps = 0.001;
	double start, finish;

	double* u0 = new double[n * n];
    
	for (int j = 0; j < area.n; ++j)
		u0[j] = 0.0;

	//srand((unsigned int)time(NULL));
	for (int i = 1; i < n - 1; ++i)
	{
		u0[i * n] = 0.0;
		for (int j = 1; j < n - 1; ++j)
		{
			u0[i * n + j] = (double)rand() / RAND_MAX;
		}
		u0[i * n + n - 1] = 0.0;
	}

	for (int j = 0; j < area.n; ++j)
		u0[(n - 1) * n + j] = 0.0;
    
	double* u_stable;
	if (pid == 0)
	{
		start = PortableGetTime();
		u_stable = solve_stable(u0, area, eps, f);
		finish = PortableGetTime();
		printf("Stable time: %.4f\n", finish-start);

		start = PortableGetTime();
	}

    double* u = solve(u0, area, eps, f);

	if (pid == 0)
	{
		finish = PortableGetTime();
		printf("Current time: %.4f\n", finish-start);

		double e;
		double max_error = 0.0;
		for (int i = 0; i < n; ++i)
		{
			for (int j = 0; j < n; ++j)
			{
				e = abs(u[i * n + j] - u_stable[i * n + j]);
				if (e != 0)
				{
					result = false;
					if (e > max_error) max_error = e;
					break;
				}
			}

			if (result == false) break;
		}

		if (result == false)
		{
			printf("Max error: %f\n", max_error);
		}
	}

	delete[] u0;
	delete[] u;
	delete[] u_stable;

	return result;
}